package cc.lirns.demo.websocket.withspring.handler;

import cc.lirns.utils.result.Result;
import cc.lirns.utils.result.ResultUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.HashMap;
import java.util.Map;

/**
 * 继承了TextWebSocketHandler 添加了一个消息处理 将接受的前端消息处理成map
 * 并且添加了心跳和测试
 * 当收到心跳包就会直接回信并结束
 * 当收到测试包就会直接返回传过来的data数据并结束
 *
 * @author lirns
 * @date 2021/10/8 16:07
 */
@Slf4j
public class MyWebSocketUtil extends TextWebSocketHandler {

    /**
     * 心跳标志
     */
    public static final String HEARTBEAT = "HEARTBEAT";

    /**
     * 测试标志
     */
    public static final String TEST = "TEST";

    /**
     * 服务端发送消息给客户端
     */
    public static void sendText(WebSocketSession session, String message, String digest) {
        try {
            log.debug("消息摘要{},具体内容{},服务端给客户端[{}]发送消息", digest, message, session.getId());
            synchronized (session) {
                session.sendMessage(new TextMessage(message));
            }
        } catch (Exception e) {
            log.error("消息摘要{},具体内容{},服务端发送消息给客户端失败：{}", digest, message, e.getMessage(), e);
        }
    }

    /**
     * 服务端发送消息给客户端
     */
    public static void sendMessage(WebSocketSession session, Result result, String digest) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            sendText(session, mapper.writeValueAsString(result), digest);
        } catch (JsonProcessingException e) {
            sendText(session, JSON.toJSONString(ResultUtil.fail()), digest);
            log.error("发送消息失败", e);
        }
    }

    /**
     * 处理发过来的消息 处理成map
     */
    public void handleMessageToMap(WebSocketSession session, Map maps, WebSocketMessage<?> message) {
        maps.putAll((Map) JSON.parse((String) message.getPayload()));
    }

    /**
     * onmessage
     */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        log.debug(this.getClass().getSimpleName() + " handleMessage");

        Map maps = new HashMap(2);

        handleMessageToMap(session, maps, message);

        String mapKey = "flag";

        if (MyWebSocketUtil.HEARTBEAT.equalsIgnoreCase(maps.get(mapKey).toString())) {
            sendMessage(session, ResultUtil.success(MyWebSocketUtil.HEARTBEAT), MyWebSocketUtil.HEARTBEAT);
            return;
        }

        if (MyWebSocketUtil.TEST.equalsIgnoreCase(maps.get(mapKey).toString())) {
            String field = (String) maps.get("field");
            sendText(session, JSON.toJSONString(maps.get("data")), "TEST");
            return;
        }

        handleMessagePost(session, message, maps);
    }

    /**
     * 消息后置处理
     */
    public void handleMessagePost(WebSocketSession session, WebSocketMessage<?> message, Map maps) throws Exception {
        log.debug(this.getClass().getSimpleName() + " handleMessagePost");
    }

//    这是获取当前登录用户的代码 跟springsecurity配合使用的 在springsecurity的配置中不能直接放行请求路径
//    /**
//     * 获取登录用户
//     *
//     * @param session 会话
//     * @return 登录用户信息
//     */
//    public SysUserDetail getLoginUser(WebSocketSession session) {
//        UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) session.getPrincipal();
//        if (token != null) {
//            return (SysUserDetail) token.getPrincipal();
//        } else {
//            throw new Exception("ws中找不到用户");
//        }
//    }

}
